// data
// 之前区块的哈希值
// 自己的哈希值：由存储在区块里的信息计算出来（data + 之前区块的哈希值）
const sha256 = require('crypto-js/sha256')

class Block {
    constructor(data, previousHash) {
        this.data = data
        this.previousHash = previousHash
        this.hash = this.computeHash()
        this.nonce = 1
    }

    computeHash() {
        return sha256(this.data + this.previousHash + this.nonce).toString();
    }

    getAnswer(difficulty) {
        let answer = ''
        for (let i = 0; i <difficulty; i++) {
            answer += 0
        }
        return answer
    }

    // 计算复合区块链要求的难度的hash
    mine(difficulty) {
        while (true) {
            this.hash = this.computeHash()
            if (this.hash.substring(0, difficulty) !== this.getAnswer(difficulty)) {
                this.nonce++
                this.hash = this.computeHash()
            } else {
                break
            }
        }
        console.log('挖矿结束', this.hash)
    }
}

class Chain {
    constructor() {
        this.chain = [this.bigBang()]
        this.difficulty = 4
    }

    // 生成祖先区块
    bigBang() {
        return new Block('我是祖先', '')
    }

    // 添加区块到区块链上
    addBlockToChain(newBlock) {
        // 找到最近一个block的hash,这个hash就是新区块的previousHash
        newBlock.previousHash = this.getLatestBlock().hash
        // newBlock.hash = newBlock.computeHash()  之前直接添加的,现在要算出复合区块链要求的难度的才添加
        newBlock.mine(this.difficulty)
        this.chain.push(newBlock)
    }

    getLatestBlock() {
        return this.chain[this.chain.length - 1]
    }

    // 验证这个当前的区块是否合法
    // 当前的数据有没有被篡改
    // 验证区块的previousHash是否等于previous的hash
    validateChain() {
        if (this.chain.length === 1) {
            return this.chain[0].hash === this.chain[0].computeHash()
        }
        // 从第二个区块开始循环验证
        for (let i = 1; i < this.chain.length; i++) {
            const blockToValidate = this.chain[i]
            // 当前数据有没有被篡改
            if (blockToValidate.hash !== blockToValidate.computeHash()) {
                console.log('数据篡改')
                return false
            }
            // 验证前后链接
            const previousBlock = this.chain[i-1]
            if (blockToValidate.previousHash !== previousBlock.hash) {
                console.log('前后区块链接断裂')
                return false
            }
        }
        return true
    }
}

const JDSun = new Chain()

const block1 = new Block('转账10元', '')
JDSun.addBlockToChain(block1)
const block2 = new Block('转账100元', '')
JDSun.addBlockToChain(block2)
/*console.log(JDSun)
console.log(JDSun.validateChain())*/

// 尝试篡改这个区块链
// 修改data
JDSun.chain[1].data = '转账1000元'
JDSun.chain[1].mine(4)
console.log(JDSun)
console.log(JDSun.validateChain())
// 同时改掉它的hash  加入proof of work之前的操作
/*
JDSun.chain[1].hash = JDSun.chain[1].computeHash()
console.log(JDSun)
console.log(JDSun.validateChain())*/

// 试试可以改吗 我也可以改吗 修改了密码再试试呢 配置了ssh不知道新密码
